package cn.firegod.demo.sharding.datasource;

import org.apache.commons.dbcp2.BasicDataSource;
import org.apache.shardingsphere.api.config.masterslave.LoadBalanceStrategyConfiguration;
import org.apache.shardingsphere.api.config.masterslave.MasterSlaveRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.KeyGeneratorConfiguration;
import org.apache.shardingsphere.api.config.sharding.ShardingRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.TableRuleConfiguration;
import org.apache.shardingsphere.api.config.sharding.strategy.InlineShardingStrategyConfiguration;
import org.apache.shardingsphere.shardingjdbc.api.MasterSlaveDataSourceFactory;
import org.apache.shardingsphere.shardingjdbc.api.ShardingDataSourceFactory;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

public class BasedJavaCodeConfig {

    public static final String CLASS_FOR_JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    Properties props = new Properties();
    private static Map<String, DataSource> dataSourceMap;
    {
        props.setProperty("sql.show", "true");
    }

    public DataSource shardingDataSource() throws SQLException {
        Map<String, DataSource> dataSourceMap = dataSourceMap();
        TableRuleConfiguration orderTableRuleConfig = new TableRuleConfiguration("order", "ds${4..6}.order${0..1}");
        orderTableRuleConfig.setDatabaseShardingStrategyConfig(new InlineShardingStrategyConfiguration("user_id", "ds$->{user_id%3 + 4}"));
        orderTableRuleConfig.setTableShardingStrategyConfig(new InlineShardingStrategyConfiguration("id", "order$->{id%2}"));
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTableRuleConfigs().add(orderTableRuleConfig);
        KeyGeneratorConfiguration defaultKeyGeneratorConfig = new KeyGeneratorConfiguration("snowflake", "id");
        shardingRuleConfig.setDefaultKeyGeneratorConfig(defaultKeyGeneratorConfig);
        shardingRuleConfig.setMasterSlaveRuleConfigs(Arrays.asList(
                new MasterSlaveRuleConfiguration("ds4", "ds4", Arrays.asList("ds4_slave1"), new LoadBalanceStrategyConfiguration("ROUND_ROBIN")),
                new MasterSlaveRuleConfiguration("ds5", "ds5", Arrays.asList("ds5_slave1"), new LoadBalanceStrategyConfiguration("ROUND_ROBIN")),
                new MasterSlaveRuleConfiguration("ds6", "ds6", Arrays.asList("ds6_slave1"), new LoadBalanceStrategyConfiguration("ROUND_ROBIN"))
        ));
        return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, props);
    }


    public DataSource masterSlaveDataSource() throws SQLException {
        MasterSlaveRuleConfiguration masterSlaveDataSource = new MasterSlaveRuleConfiguration("ds_ms", "ds1", Arrays.asList("ds2", "ds3"), new LoadBalanceStrategyConfiguration("ROUND_ROBIN"));
        return MasterSlaveDataSourceFactory.createDataSource(dataSourceMap(), masterSlaveDataSource, props);
    }


    protected Map<String, DataSource> dataSourceMap() {
        if (dataSourceMap != null) {
            return dataSourceMap;
        }
        synchronized (this) {
            // 配置真实数据源
            dataSourceMap = new HashMap<>();
        }

        dataSourceMap.put("ds1", createBasicDataSource("jdbc:mysql://localhost:33080/test"));
        dataSourceMap.put("ds2", createBasicDataSource("jdbc:mysql://localhost:33081/test"));
        dataSourceMap.put("ds3", createBasicDataSource("jdbc:mysql://localhost:33082/test"));

        dataSourceMap.put("ds4", createBasicDataSource("jdbc:mysql://localhost:33083/test"));
        dataSourceMap.put("ds5", createBasicDataSource("jdbc:mysql://localhost:33084/test"));
        dataSourceMap.put("ds6", createBasicDataSource("jdbc:mysql://localhost:33085/test"));

        dataSourceMap.put("ds4_slave1", createBasicDataSource("jdbc:mysql://localhost:33083/test"));
        dataSourceMap.put("ds5_slave1", createBasicDataSource("jdbc:mysql://localhost:33084/test"));
        dataSourceMap.put("ds6_slave1", createBasicDataSource("jdbc:mysql://localhost:33085/test"));
        return dataSourceMap;
    }

    private BasicDataSource createBasicDataSource(String url) {
        BasicDataSource ds4 = new BasicDataSource();
        ds4.setDriverClassName(CLASS_FOR_JDBC_DRIVER);
        ds4.setUrl(url);
        ds4.setUsername("root");
        ds4.setPassword("12345678");
        return ds4;
    }
}
